package com.cskaoyan.javase.oop3._2inner._4anonymous._0introduction;

/**
 * 匿名内部类的引入
 * 匿名内部类是特殊的局部内部类,它仍然定义在局部位置,作用域仅在局部位置内部
 * 它的成员特点,修饰符,访问特点等和局部内部类是一致的,所以不再赘述.
 *
 * 匿名内部类的语法会比局部内部类更加简洁,以往我们写局部内部类的目的是为了获取某个类/接口的子类对象
 *      这时这个子类的名字我们根本不关心,只需要获取子类对象就行了
 *      于是就出现了匿名(局部)内部类
 *
 * 匿名内部类,是一个没有名字类,所以匿名内部类实际上不是一个类,而是一个对象.
 * 语法:
 *      new 类名/接口名(){
 *          // 类体
 *      };
 * 解释一下这个语法:
 *      1.new表示创建对象,所以匿名内部类的语法整体表示一个对象,而不是一个类
 *      2.new后面的类名可以是普通类,也可以是抽象类.
 *      3.匿名内部类的语法中隐含继承和实现,会得到一个类名或者接口名的子类对象.
 *      4.new后面的部分:
 *          类名/接口名(){
 *              // 类体
 *          };
 *        是类名或者接口名的子类的类体,这个子类叫啥是不知道的,所以是匿名内部类
 *        可以在这个类体中,重写父类的方法,新增自己的成员等等.
 *      5.()表示在子类对象初始化时,调用父类的构造器
 *          注: 接口没有构造器,这仅限于类去使用
 *          对于接口而言()没有任何作用
 *
 *
 *
 *  匿名内部类对象怎么用?
 *       1.引用接收去使用
 *          虽然匿名内部类对象是一个子类对象,但是这个子类的名字是不知道的,所以只能使用父引用接收.
 *          引用接收后,用引用调用方法即可
 *
 *       2.直接作为一个匿名对象使用
 *          直接在匿名内部类对象语法大括号的后面
 *          直接点调用方法/访问成员变量
 *
 *  对比一下两种方式:
 *          1.引用接收
 *          优点: 这个匿名内部类对象,可以用多次
 *          缺点:
 *              a.比较麻烦,需要引用接收
 *              b.由于子类是匿名的,无法强转,是真的无法访问子类独有成员.
 *
 *         2.直接使用
 *         优点:
 *              1.可以访问子类独有成员
 *              2.更简单
 *         缺点:
 *              一次性的,不能使用多次
 *
 *  总的来说,如果有多次使用对象的需求,并且不需要访问子类独有成员,那就用引用接收
 *  相反如果仅用一次,从快捷方便的角度来说,就直接使用
 *  当然如果访问子类独有成员,必然要直接使用
 *
 * @since 16:12
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        class ASon extends A {
            @Override
            void test() {
                System.out.println("ASon");
            }
        }
        ASon a = new ASon();
        a.test();

        // 用匿名内部类简化
        A a2 = new A(18) {
            // A的子类类体
            @Override
            void test() {
                System.out.println("我是高级的写法,我是普通类的匿名内部类对象");
            }

            // 独有方法
            void test2(){}
        };
        a2.test();
        a2.test();
        a2.test();
        // ((A) a2).test2();

        // 用匿名内部类创建IA接口的子类对象
        new IA() {
            @Override
            public void test() {
                System.out.println("我也很高级,我是接口的匿名内部类对象");
            }
            // 独有方法
            void test2(){}
        };

    }
}

class A {
    int a;

    public A(int a) {
        this.a = a;
    }

    public A() {
    }

    void test() {
        System.out.println("A");
    }
}

interface IA {
    void test();
}